import { useRef } from "react";
import { useDrag, useDrop } from "react-dnd";
import { CARD } from "./../../dragType";
type cardItem = {
  name: string;
  id?: number;
  index: number;
  moveCard: (index1: number, index2: number) => void;
};
const style = {
  width: "400px",
  background: "red",
  margin: "5px",
  padding: "5px",
  border: "1px solid gray",
};
// useDrag 对应的项目叫做拖动源，useDrop对应的项目叫做放置目标 DropTarget
function Card(props: cardItem) {
  const ref = useRef<any>();
  const { name, id, index, moveCard } = props;
  //useDrag hook 提供了一个组件作为拖动源链接到react dnd系统中的方法
  let [dragProps, drag] = useDrag({
    type: CARD, //拖拽的类型
    //必须是一个函数或者说是一个对象，她是用于描述拖动源的普通js对象
    item: () => ({ id, index }),
    //用来收集属性，并且返回一个js对象，返回值会合并到你的组件属性中
    collect: (monitor) => ({
      //monitor 里面存放的是一些拖动状态，当拖动状态发生变化时会通知组件获取新的属性并刷新组件
      isDragging: monitor.isDragging(),
    }),
  });
  const { isDragging } = dragProps;
  //拖动源的连接器，链接你的真实dom和react dnd系统
  drag(ref);

  const opacity = isDragging ? 0.2 : 1;

  //放置目标
  const [, drop] = useDrop({
    accept: CARD, //一个字符串，这个放置目标只会对指定的拖动源发生反应
    collect: () => ({}),
    hover: (item: cardItem, monitor: any) => {
      const dragIndex: number = item.index; //被拖动卡片的索引
      const hoverIndex: number = index; //悬停的卡片的索引
      if (dragIndex === hoverIndex) {
        return;
      }
      const { top, bottom } = ref.current.getBoundingClientRect();
      const halfOfHoverheight = (bottom - top) / 2;
      const { y } = monitor.getClientOffset();
      const hoverClientY = y - top;
      if (
        (dragIndex < hoverIndex && hoverClientY > halfOfHoverheight) ||
        (dragIndex > hoverIndex && hoverClientY < halfOfHoverheight)
      ) {
        moveCard(dragIndex, hoverIndex);
        item.index = hoverIndex;
      }
    },
  });
  drop(ref);
  return (
    <div ref={ref} style={{ ...style, opacity }}>
      {name}
    </div>
  );
}

export default Card;
